package com.tianhai.db;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.tianhai.db.parser.ast.CreateTableStatement;
import com.tianhai.db.parser.ast.DeleteStatement;
import com.tianhai.db.parser.ast.InsertStatement;
import com.tianhai.db.parser.ast.SelectStatement;
import com.tianhai.db.parser.ast.Statement;
import com.tianhai.db.parser.ast.UpdateStatement;

/**
 * SQL执行器 - 基于AST执行SQL语句
 */
public class Executor {
    
    // 表元数据存储 <表名, 表结构>
    private final Map<String, TableSchema> tables = new HashMap<>();
    
    // 表数据存储 <表名, 行数据列表>
    private final Map<String, List<Map<String, Object>>> tableData = new HashMap<>();
    
    /**
     * 执行SQL语句
     */
    public ExecuteResult execute(Statement stmt) {
        switch (stmt.getType()) {
            case CREATE_TABLE:
                return executeCreateTable((CreateTableStatement) stmt);
            case INSERT:
                return executeInsert((InsertStatement) stmt);
            case SELECT:
                return executeSelect((SelectStatement) stmt);
            case UPDATE:
                return executeUpdate((UpdateStatement) stmt);
            case DELETE:
                return executeDelete((DeleteStatement) stmt);
            default:
                return new ExecuteResult(false, "不支持的语句类型");
        }
    }
    
    /**
     * 执行CREATE TABLE
     */
    private ExecuteResult executeCreateTable(CreateTableStatement stmt) {
        String tableName = stmt.getTableName();
        if (tables.containsKey(tableName)) {
            return new ExecuteResult(false, "表已存在: " + tableName);
        }
        
        tables.put(tableName, new TableSchema(stmt.getColumns()));
        tableData.put(tableName, new ArrayList<>());
        
        return new ExecuteResult(true, "创建表成功: " + tableName);
    }
    
    /**
     * 执行INSERT
     */
    private ExecuteResult executeInsert(InsertStatement stmt) {
        String tableName = stmt.getTableName();
        if (!tables.containsKey(tableName)) {
            return new ExecuteResult(false, "表不存在: " + tableName);
        }
        
        Map<String, Object> row = new HashMap<>();
        List<String> columns = stmt.getColumns();
        List<Object> values = stmt.getValues();
        
        for (int i = 0; i < columns.size(); i++) {
            row.put(columns.get(i), values.get(i));
        }
        
        tableData.get(tableName).add(row);
        return new ExecuteResult(true, "插入成功", 1);
    }
    
    /**
     * 执行SELECT
     */
    private ExecuteResult executeSelect(SelectStatement stmt) {
        String tableName = stmt.getTableName();
        if (!tables.containsKey(tableName)) {
            return new ExecuteResult(false, "表不存在: " + tableName);
        }
        
        List<Map<String, Object>> rows = tableData.get(tableName);
        List<Map<String, Object>> result = new ArrayList<>();
        
        // 过滤WHERE条件
        for (Map<String, Object> row : rows) {
            if (matchWhere(row, stmt.getWhereClause())) {
                result.add(projectColumns(row, stmt.getColumns()));
            }
        }
        
        // LIMIT
        if (stmt.getLimit() != null && result.size() > stmt.getLimit()) {
            result = result.subList(0, stmt.getLimit());
        }
        
        return new ExecuteResult(true, "查询成功", result);
    }
    
    /**
     * 执行UPDATE
     */
    private ExecuteResult executeUpdate(UpdateStatement stmt) {
        String tableName = stmt.getTableName();
        if (!tables.containsKey(tableName)) {
            return new ExecuteResult(false, "表不存在: " + tableName);
        }
        
        List<Map<String, Object>> rows = tableData.get(tableName);
        int updateCount = 0;
        
        for (Map<String, Object> row : rows) {
            if (matchWhere(row, stmt.getWhereClause())) {
                for (UpdateStatement.Assignment assign : stmt.getAssignments()) {
                    row.put(assign.getColumnName(), assign.getValue());
                }
                updateCount++;
            }
        }
        
        return new ExecuteResult(true, "更新成功", updateCount);
    }
    
    /**
     * 执行DELETE
     */
    private ExecuteResult executeDelete(DeleteStatement stmt) {
        String tableName = stmt.getTableName();
        if (!tables.containsKey(tableName)) {
            return new ExecuteResult(false, "表不存在: " + tableName);
        }
        
        List<Map<String, Object>> rows = tableData.get(tableName);
        int deleteCount = 0;
        
        Iterator<Map<String, Object>> iterator = rows.iterator();
        while (iterator.hasNext()) {
            if (matchWhere(iterator.next(), stmt.getWhereClause())) {
                iterator.remove();
                deleteCount++;
            }
        }
        
        return new ExecuteResult(true, "删除成功", deleteCount);
    }
    
    /**
     * 检查行是否匹配WHERE条件
     */
    private boolean matchWhere(Map<String, Object> row, SelectStatement.WhereClause where) {
        if (where == null) return true;
        
        for (SelectStatement.Condition cond : where.getConditions()) {
            Object value = row.get(cond.getColumnName());
            if (!matchCondition(value, cond.getOperator(), cond.getValue())) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 检查单个条件
     */
    @SuppressWarnings("unchecked")
    private boolean matchCondition(Object value, SelectStatement.Operator op, Object target) {
        if (value == null) return false;
        
        switch (op) {
            case EQUAL:
                return value.equals(target);
            case NOT_EQUAL:
                return !value.equals(target);
            case LESS_THAN:
                return ((Comparable) value).compareTo(target) < 0;
            case GREATER_THAN:
                return ((Comparable) value).compareTo(target) > 0;
            case LESS_THAN_OR_EQUAL:
                return ((Comparable) value).compareTo(target) <= 0;
            case GREATER_THAN_OR_EQUAL:
                return ((Comparable) value).compareTo(target) >= 0;
            case LIKE:
                return value.toString().contains(target.toString());
            default:
                return false;
        }
    }
    
    /**
     * 投影指定列
     */
    private Map<String, Object> projectColumns(Map<String, Object> row, List<String> columns) {
        if (columns == null) return new HashMap<>(row); // SELECT *
        
        Map<String, Object> result = new HashMap<>();
        for (String col : columns) {
            result.put(col, row.get(col));
        }
        return result;
    }
    
    /**
     * 表结构
     */
    static class TableSchema {
        final List<CreateTableStatement.ColumnDefinition> columns;
        
        TableSchema(List<CreateTableStatement.ColumnDefinition> columns) {
            this.columns = columns;
        }
    }
    
    /**
     * 执行结果
     */
    public static class ExecuteResult {
        private final boolean success;
        private final String message;
        private final int affectedRows;
        private final List<Map<String, Object>> resultSet;
        
        public ExecuteResult(boolean success, String message) {
            this(success, message, 0, null);
        }
        
        public ExecuteResult(boolean success, String message, int affectedRows) {
            this(success, message, affectedRows, null);
        }
        
        public ExecuteResult(boolean success, String message, List<Map<String, Object>> resultSet) {
            this(success, message, 0, resultSet);
        }
        
        public ExecuteResult(boolean success, String message, int affectedRows, List<Map<String, Object>> resultSet) {
            this.success = success;
            this.message = message;
            this.affectedRows = affectedRows;
            this.resultSet = resultSet;
        }
        
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
        public int getAffectedRows() { return affectedRows; }
        public List<Map<String, Object>> getResultSet() { return resultSet; }
        
        @Override
        public String toString() {
            if (resultSet != null) {
                return message + ", 结果集大小: " + resultSet.size();
            }
            return message + (affectedRows > 0 ? ", 影响行数: " + affectedRows : "");
        }
    }
}
